package evi.com.evi.application;

import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;

import evi.com.evi.utils.SPUtils;

public class CrashHandler implements UncaughtExceptionHandler {

	private Context context; // 全局的上下文
	private UncaughtExceptionHandler defaultExceptionHandler;

	/**
	 * 单一存在
	 */
	private CrashHandler(Context context) {
		this.context = context;
		defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
		Thread.setDefaultUncaughtExceptionHandler(this);
	}
	private static CrashHandler instance;
	public static CrashHandler getInstance(Context context) {
		if (instance == null)
				synchronized (CrashHandler.class) {
					if (instance == null)
					instance = new CrashHandler(context);
				}
		return instance;
	}

	@Override
	public void uncaughtException(Thread t, Throwable e) {
		if (!handlerException(e) && defaultExceptionHandler != null) {
			defaultExceptionHandler.uncaughtException(t, e);
		} else {
			SystemClock.sleep(3000);
//			AlarmManager mgr = (AlarmManager) context
//					.getSystemService(Context.ALARM_SERVICE);
//			Intent intent = new Intent(context, SplashActivity.class);
//			intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//			intent.putExtra("crash", true);
//			PendingIntent restartIntent = PendingIntent.getActivity(context, 0,
//					intent, PendingIntent.FLAG_ONE_SHOT);
//			mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,
//					restartIntent); // 1秒钟后重启应用
			android.os.Process.killProcess(android.os.Process.myPid());
			System.exit(0);
			System.gc();
		}
	}

	/**
	 * @return 异常处理
	 */
	private boolean handlerException(final Throwable e) {
		e.printStackTrace();
		// 此处可上传错误日志信息
		// 友好退出
		new Thread() {
			public void run() {
				try {
					Log.e("Error", "error捕捉");
					// 判断SD卡是否存在
					if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
						// 1.获取当前程序的版本号. 版本的id
						String versioninfo = getVersionInfo();
						// 2.获取手机的硬件信息.
						String mobileInfo = getMobileInfo();
						// 3.把错误的堆栈信息 获取出来
						String errorinfo = getErrorInfo(e);
						// 绝对路径
						String filePath = Environment.getExternalStorageDirectory() + "/Creditmate/" + "exception.txt";
						
						String time = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date());
						final String msg = "\r\n\r\n发生异常时间:" + time + "\r\n\r\n当前程序的版本号:"
								+ versioninfo + "\r\n\r\n手机的硬件信息:" + mobileInfo +"\r\n\r\n错误信息:"+ errorinfo;
						//存取错误日志到sp
						SPUtils.put(context, "errorMsg", msg);
						FileWriter fileWriter = new FileWriter(filePath, false);
						fileWriter.write(msg);
						fileWriter.flush();
						fileWriter.close();
						
						Looper.prepare();
//						Toast.makeText(context, "数据有误，3秒后重新登录", 1).show();
						Toast.makeText(context, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
						Looper.loop();
					}
				} catch (Exception e) {
				}
			};
		}.start();
		return true;
	}
	
	/**
	 * 获取错误的信息
	 * 
	 * @return
	 */
	public String getErrorInfo(Throwable ex) {
		Writer writer = null;
		PrintWriter pw = null;
		StringBuffer buffer = null;
		try {
			writer = new StringWriter();
			pw = new PrintWriter(writer);
			ex.printStackTrace(pw);
			pw.close();
			String error = writer.toString();
			buffer = new StringBuffer("\r\n错误信息:" + ex.getMessage());
			buffer.append("\r\n\r\n详细错误信息:" + error);
			// 打印错误信息
			ex.printStackTrace();

		} catch (Exception e) {
			e.printStackTrace();
			return "错误信息未能捕获成功";
		}
		return buffer.toString();
	}

	/**
	 * 获取手机的硬件信息
	 * 
	 * @return
	 */
	public String getMobileInfo() {
		StringBuffer sb = new StringBuffer();
		// 通过反射获取系统的硬件信息
		try {

			Field[] fields = Build.class.getDeclaredFields();
			for (Field field : fields) {
				// 暴力反射 ,获取私有的信息
				field.setAccessible(true);
				String name = field.getName();
				String value = field.get(null).toString();
				sb.append(name + ":" + value);
				sb.append("\r\n");
			}
		} catch (Exception e) {
			e.printStackTrace();
			return "手机信息未知";
		}
		return sb.toString();
	}

	/**
	 * 获取手机的版本信息
	 * 
	 * @return
	 */
	public String getVersionInfo() {
		try {
			PackageManager pm = context.getPackageManager();
			PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0);
			return info.versionName;
		} catch (Exception e) {
			e.printStackTrace();
			return "版本号未知";
		}
	}
}
